﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.Generic;
using DiscoveryLogic.UI.Layouts.Controls;
using DiscoveryLogic.DataServices.DataSources;
using DiscoveryLogic.UI.Layouts.CustomEventArgs;
using DiscoveryLogic.UI.Layouts.DataAccesses;

namespace DiscoveryLogic.UI.Layouts.ContentScreens
{
    public partial class View360 : UserControl
    {
       
        #region Private Variables

            private Canvas topCanvas;
            private List<RadialAspect> alist = new List<RadialAspect>();
            private DashboardForm parentWindow;
            
            // Constants for the "man" icon
            private const double manIconInitialScale = 1.6;
            private const double manIconLeft = 265;
            private const double manIconTop = 63;
            private const int manIconZIndex = 70;

        #endregion

        #region Constructors

            public View360(DashboardForm parentWindow)
            {
                InitializeComponent();
                topCanvas = View360Canvas;
                this.parentWindow = parentWindow;

                // Add loaded event
                this.Loaded += new RoutedEventHandler(View360_Loaded);
                innerContainerPanel.ItemCrossedRing += OnItemCrossedRing;
                innerContainerPanel.BeginDrag += OnBeginDrag;
                innerContainerPanel.EndDrag += OnEndDrag;
                outerContainerPanel.ItemCrossedRing += OnItemCrossedRing;
                outerContainerPanel.BeginDrag += OnBeginDrag;
                outerContainerPanel.EndDrag += OnEndDrag;

                // Register the two radial panels with each other, so we can drag between them, and animate accordingly when dragging
                innerContainerPanel.RegisterPanel(ref outerContainerPanel);
                outerContainerPanel.RegisterPanel(ref innerContainerPanel);
            }

        #endregion

        #region Public Methods

        /// <summary>
        /// This method sets the Z-Index of the aspects such that items lower on the panel will be higher in the Z-index than others.
        /// This stops icons from overlapping each other inappropriately. It is called when items on the RadialPanel are moved.
        /// </summary>
        public void FixItemZOrder()
        {
            int zIndex = alist.Count;

            // Re-apply the Z-index of each aspect on the main panel so that items on the bottom half have a higher Z-index.
            // This is typically called after an item has finished being moved via a drag operation.
            // This is a slight hack, as currently we do not take into account which panel the items are on. An improvement to the RadialPanel
            // would be for it to handle ZIndex itself.
            foreach (RadialAspect item in alist)
            {
                item.ZOrder = zIndex;
                --zIndex;
            }
        }

        #endregion

        #region Helper Methods

        /// <summary>
        /// We use this event to create the various icons and add them to the RadialPanels, based on the list of Accounts retrieved from the Account Manager.
        /// </summary>
        private void View360_Loaded(object sender, EventArgs e)
        {
            // Create Man Icon for 'Favorites' disc
            Canvas carousel = FindName("Carousel") as Canvas;

            Aspect manIcon = new Aspect("DiscoveryLogic.UI.Layouts.Aspects.Man.xaml", ((double) carousel.GetValue(Canvas.LeftProperty)) + manIconLeft, ((double) carousel.GetValue(Canvas.TopProperty)) + manIconTop, this);
            manIcon.Scale = manIconInitialScale;
            manIcon.ZOrder = manIconZIndex;
            topCanvas.Children.Add(manIcon);

            Canvas innerCarousel = FindName("LayoutRoot") as Canvas;

            // Create Account Manager to retrieve list of accounts from web service
            AccountManager accManager = new AccountManager();
            List<Account> listOfAccounts = accManager.GetAccounts();

            // Determine how many items to put on 'Favorites' disc
            int numOnFaveDisc = Constants.faveContainerMaxItems;

            innerContainerPanel.MaxItems = numOnFaveDisc;

            // Create aspects and put them on the 'Favorites' disc
            int i = 0;

            foreach(Account account in listOfAccounts)
            {
                alist.Add(new RadialAspect(account.VisualPath, this));
                // Split the items between the inner and outer panels
                // Note that the "MaxItems" setting on the panel does not stop someone from adding more items to it. It only affects
                // what happens when a user drags item on to the panel.
                if (i < numOnFaveDisc)
                    innerContainerPanel.Children.Add(alist[i].Control);
                else
                    outerContainerPanel.Children.Add(alist[i].Control);
                // We need to attach the event handlers after the control is added to the main tree, otherwise FindName() fails
                alist[i].AttachHandlers();
                // Set up some other info we need
                alist[i].Model = account;
                alist[i].ZOrder = numOnFaveDisc - i;
                // Set Aspect click handler (so that when it is clicked, we will open the related screen).
                alist[i].AspectClick += new EventHandler(parentWindow.OnAspectClicked);
                ++i;
            }
        }

        void OnBeginDrag(object sender, RoutedEventArgs e)
        {
            // Make the outer panel visible now that the user has started dragging an item on one of the RadialPanels.
            Storyboard story = topCanvas.FindName("DisplayOuterPanel") as Storyboard;

            if (story != null)
                story.Begin();
        }

        void OnEndDrag(object sender, RoutedEventArgs e)
        {
            // Make the outer panel invisible now that the user has stopped dragging an item
            Storyboard story = topCanvas.FindName("HideOuterPanel") as Storyboard;

            if (story != null)
                story.Begin();
        }

        void OnItemCrossedRing(object sender, ItemCrossedRingEventArgs e)
        {
            // If a user drags from the outer panel to the inner panel, we make the label visible.
            // If they drag from the inner to the outer, we hide the label.
            if (e.ToRing == innerContainerPanel)
                ((RadialItemControl) e.ItemMoved).Label.Opacity = 1;
            else if (e.ToRing == outerContainerPanel)
                ((RadialItemControl)e.ItemMoved).Label.Opacity = 0;
        }

        #endregion

    }
}
